package com.bys.system.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bys.constant.CrmSystemConstant;
import com.bys.exception.BysOaSystemException;
import com.bys.system.mapper.SysRoleMenuMapper;
import com.bys.system.model.SysMenuModel;
import com.bys.system.mapper.SysMenuMapper;
import com.bys.system.model.SysUserRoleModel;
import com.bys.system.service.ISysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bys.system.service.ISysUserRoleService;
import com.bys.system.vo.MetaVo;
import com.bys.system.vo.RouterVo;
import com.bys.system.vo.SysMenuVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * PackageName:  com.bys.system.service.impl
 * ClassName:    SysMenuServiceImpl
 * Description:  菜单表 服务实现类
 * Author:       bys
 * Date:         2023-03-31
 **/
@Slf4j
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuModel> implements ISysMenuService {
    @Resource
    private SysMenuMapper sysMenuMapper;
    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;
    @Resource
    private ISysUserRoleService sysUserRoleService;

    @Override
    public void deleteLogic(Long id) {
        SysMenuModel sysMenuModel = new SysMenuModel();
        sysMenuModel.setId(id);
        sysMenuModel.setIsDeleted(Boolean.TRUE);
        sysMenuMapper.updateById(sysMenuModel);
    }

    @Override
    public List<SysMenuVo> getMenu() {

        List<SysMenuVo> menuList = sysMenuMapper.selectMenu(CrmSystemConstant.MENU_ROOT);
        getMenuTree(menuList);
        return menuList;
    }

    @Override
    public List<SysMenuVo> findRoleMenu(Long roleId) {
        List<SysMenuVo> roleMenu = new ArrayList<>();
        // 如果是管理员查询全部的权限
        if (CrmSystemConstant.admin_RoleId.equals(roleId)) {
            List<SysMenuModel> adminMenu = sysMenuMapper.selectList(Wrappers.lambdaQuery(SysMenuModel.class).eq(SysMenuModel::getIsDeleted, Boolean.FALSE));
            roleMenu = adminMenu.stream().map(menu -> {
                SysMenuVo menuVo = new SysMenuVo();
                BeanUtils.copyProperties(menu,menuVo);
                return menuVo;
            }).collect(Collectors.toList());
        } else {
           roleMenu = sysRoleMenuMapper.selectRoleMenu(roleId);
        }
        return getMenuChild(roleMenu);
    }

    private List<SysMenuVo> getMenuChild(List<SysMenuVo> roleMenu) {
        Map<Integer, List<SysMenuVo>> map = roleMenu.stream().collect(Collectors.groupingBy(SysMenuVo::getType));
        if(map.containsKey(CrmSystemConstant.CATALOGUE)){
            getMenuTree(map.get(CrmSystemConstant.CATALOGUE));
            return map.get(CrmSystemConstant.CATALOGUE);
        }else if(map.containsKey(CrmSystemConstant.MENU)){
            getMenuTree(map.get(CrmSystemConstant.MENU));
            return map.get(CrmSystemConstant.MENU);
        }else if(map.containsKey(CrmSystemConstant.BUTTON)){
            getMenuTree(map.get(CrmSystemConstant.BUTTON));
            return map.get(CrmSystemConstant.BUTTON);
        }
        return roleMenu;
    }

    @Override
    public List<RouterVo> findUserMenu(Long userId) {
        List<SysMenuModel> menuList = null;
        List<Long> roleIds = sysUserRoleService.list(Wrappers.lambdaQuery(SysUserRoleModel.class).eq(SysUserRoleModel::getUserId, userId)).stream().map(SysUserRoleModel::getRoleId).collect(Collectors.toList());
        if(roleIds.contains(CrmSystemConstant.admin_RoleId)){
            menuList = sysMenuMapper.selectList(Wrappers.lambdaQuery(SysMenuModel.class).eq(SysMenuModel::getIsDeleted, Boolean.FALSE).eq(SysMenuModel::getStatus, CrmSystemConstant.ENABLE_STATUS));
        }else{
            menuList = baseMapper.selectMenuByUserId(userId);
        }
        List<SysMenuModel> sysMenuTreeList = buildTree(menuList);
        //构建成框架要求的路由结构
        List<RouterVo> routerList = this.buildRouter(sysMenuTreeList);
        return routerList;
    }

    private List<RouterVo> buildRouter(List<SysMenuModel> sysMenuTreeList) {
        //创建list集合，存储最终数据
        List<RouterVo> routers = new ArrayList<>();
        //menus遍历
        for(SysMenuModel menu : sysMenuTreeList) {
            RouterVo router = new RouterVo();
            router.setHidden(false);
            router.setAlwaysShow(false);
            router.setPath(getRouterPath(menu));
            router.setComponent(menu.getComponent());
            router.setMeta(new MetaVo(menu.getName(), menu.getIcon()));
            //下一层数据部分
            List<SysMenuModel> children = menu.getChildren();
            if(menu.getType().intValue() == 1) {
                //加载出来下面隐藏路由
                List<SysMenuModel> hiddenMenuList = children.stream()
                        .filter(item -> !org.springframework.util.StringUtils.isEmpty(item.getComponent()))
                        .collect(Collectors.toList());
                for(SysMenuModel hiddenMenu : hiddenMenuList) {
                    RouterVo hiddenRouter = new RouterVo();
                    //true 隐藏路由
                    hiddenRouter.setHidden(true);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setPath(getRouterPath(hiddenMenu));
                    hiddenRouter.setComponent(hiddenMenu.getComponent());
                    hiddenRouter.setMeta(new MetaVo(hiddenMenu.getName(), hiddenMenu.getIcon()));

                    routers.add(hiddenRouter);
                }

            } else {
                if(!CollectionUtils.isEmpty(children)) {
                    if(children.size() > 0) {
                        router.setAlwaysShow(true);
                    }
                    //递归
                    router.setChildren(buildRouter(children));
                }
            }
            routers.add(router);
        }
        return routers;
    }
    public String getRouterPath(SysMenuModel menu) {
        String routerPath = "/" + menu.getPath();
        if(menu.getParentId().intValue() != 0) {
            routerPath = menu.getPath();
        }
        return routerPath;
    }

    //使用递归方法建菜单
    public static List<SysMenuModel> buildTree(List<SysMenuModel> sysMenuList) {
        //创建list集合，用于最终数据
        List<SysMenuModel> trees = new ArrayList<>();
        //把所有菜单数据进行遍历
        for(SysMenuModel sysMenu:sysMenuList) {
            //递归入口进入
            //parentId=0是入口
            if(sysMenu.getParentId() == 0) {
                trees.add(getChildren(sysMenu,sysMenuList));
            }
        }
        return trees;
    }
    public static SysMenuModel getChildren(SysMenuModel sysMenu,
                                      List<SysMenuModel> sysMenuList) {
        sysMenu.setChildren(new ArrayList<SysMenuModel>());
        //遍历所有菜单数据，判断 id 和 parentId对应关系
        for(SysMenuModel it: sysMenuList) {
            if(sysMenu.getId().longValue() == it.getParentId().longValue()) {
                if (sysMenu.getChildren() == null) {
                    sysMenu.setChildren(new ArrayList<>());
                }
                sysMenu.getChildren().add(getChildren(it,sysMenuList));
            }
        }
        return sysMenu;
    }

    @Override
    public List<String> findUserPermission(Long userId) {
        List<SysMenuModel> permissionList = null;
        if(CrmSystemConstant.admin_RoleId.equals(userId)){
            permissionList =  sysMenuMapper.selectList(Wrappers.lambdaQuery(SysMenuModel.class).eq(SysMenuModel::getIsDeleted, Boolean.FALSE).eq(SysMenuModel::getStatus, CrmSystemConstant.ENABLE_STATUS));
        }else {
            permissionList = sysMenuMapper.selectMenuByUserId(userId);
        }
        return permissionList.stream().map(SysMenuModel::getPerms).filter(StringUtils::isNotBlank).collect(Collectors.toList());
    }

    private List<RouterVo> buildMenus(List<SysMenuVo> menuList) {
        List<RouterVo> routes = new ArrayList<>();
        menuList.forEach(menu ->{
            RouterVo router = new RouterVo();
            // 目录
            if(CrmSystemConstant.CATALOGUE.equals(menu.getType())){
                router.setHidden(false);
                router.setAlwaysShow(true);
                router.setPath(getRouterPath(menu.getPath()));
                router.setMeta(new MetaVo(menu.getName(),menu.getIcon()));
                router.setComponent(menu.getComponent());
                router.setChildren(buildMenus(menu.getChildren()));
            }  if(CrmSystemConstant.MENU.equals(menu.getType())){
                router.setHidden(false);
                router.setAlwaysShow(true);
                router.setComponent(menu.getComponent());
                router.setMeta(new MetaVo(menu.getName(),menu.getIcon()));
                router.setPath(getRouterPath(menu.getPath()));
                router.setChildren(buildMenus(menu.getChildren()));
            }else{
                router.setHidden(true);
                router.setAlwaysShow(false);
                router.setMeta(new MetaVo(menu.getName(),menu.getIcon()));
                router.setComponent(menu.getComponent());
                router.setPath(getRouterPath(menu.getPath()));
            }
            routes.add(router);
        });
        return routes;
    }
    private String getRouterPath(String path) {
        String routerPath = null;
        if(StringUtils.isNotBlank(path)){
            routerPath = "/" +path;
        }
        return routerPath;
    }

    private void getMenuTree(List<SysMenuVo> menuList) {
        menuList.forEach(menu -> {
            if (menu != null) {
                List<SysMenuVo> sysMenuVos = sysMenuMapper.selectMenu(menu.getId());
                menu.setChildren(sysMenuVos);
                getMenuTree(sysMenuVos);
            }
        });
    }
}
